package xyz.scootaloo.kami.server.service

import io.vertx.core.Future
import io.vertx.core.file.AsyncFile
import io.vertx.core.file.FileSystem
import io.vertx.ext.web.FileUpload
import io.vertx.kotlin.core.file.openOptionsOf
import io.vertx.kotlin.coroutines.await
import xyz.scootaloo.kami.server.verticle.vertx

/**
 * 文件助手, 提供通用的文件操作的方法
 *
 * @author flutterdash@qq.com
 * @since 2022/3/3 20:11
 */
interface FileUploadHelper {

    fun Collection<FileUpload>.asyncDelete() = this.forEach { it.asyncDelete() }

    /**
     * 由于BodyHandler中有一个参数, 可以自动在请求响应结束之后删除上传的文件
     * 所以这里不用再手动删除, 但是还是通过这个方法记录文件删除的时机
     */
    fun FileUpload.asyncDelete() {
//        return vertx.fileSystem().delete(uploadedFileName()).onFailure {
//            println("hello world")
//        }
    }

    /**
     * 将文件转移到另一个地方
     *
     * 这个方法用于将一个文件块(完整文件的一部分), 转移到另一个临时文件中去
     *
     * 假设有一个完成文件为       临时文件为(路径为test.tmp)
     * '102030405060708090'   '000000000000000000'
     * 按照每4个字符进行拆分, 其中编号为1的文件块内容为'3040'
     *
     * 调用 fileChunk.transferTo(test.tmp, 4)后, 此临时文件的内容为
     * '000030400000000000'
     *
     * @param absoluteTarget 目标位置, 这个位置是绝对路径
     * @param offset 偏移量
     */
    suspend fun FileUpload.transferTo(absoluteTarget: String, offset: Long) {
        val fs = vertx.fileSystem()
        val buff = fs.readFile(uploadedFileName()).await()
        val aFile = openFile(fs, absoluteTarget).await()
        aFile.write(buff, offset).await()
        aFile.close() // 关闭目标文件
        asyncDelete() // 删除临时文件
    }

    private fun openFile(fs: FileSystem, filepath: String): Future<AsyncFile> {
        return fs.open(filepath, openOptionsOf())
    }
}